package judesart.app.server;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Random;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import judesart.app.client.controller.ArtworkController;
import judesart.app.domain.Artist;
import judesart.app.domain.Artwork;
import judesart.app.domain.ArtworkMessage;
import judesart.app.domain.Gallery;
import judesart.app.domain.Project;
import judesart.app.domain.Room;
import judesart.app.domain.RoomArtwork;
import judesart.app.domain.User;
import judesart.app.repository.ArtistDAO;
import judesart.app.repository.ArtworkDAO;
import judesart.app.repository.GalleryDAO;
import judesart.app.repository.ProjectDAO;
import judesart.app.repository.UserDAO;
import judesart.app.repository.UserDAOImpl;
import judesart.app.service.UserService;
import judesart.app.shared.ArtworkShort;
import judesart.app.shared.SearchResult;
import judesart.app.shared.SelectProject;
import judesart.app.shared.ValidationException;
import judesart.common.bean.ApplicationContextProvider;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class ArtworkControllerImpl extends RemoteServiceServlet implements
        ArtworkController {
    private static final long serialVersionUID = 1L;

    private final static Log LOGGER = LogFactory.getLog(ArtworkControllerImpl.class);

    ArtistDAO artistDAO = ApplicationContextProvider.getCtx().getBean(
            ArtistDAO.class);
    UserService userService = ApplicationContextProvider.getCtx().getBean(
            UserService.class);
    ArtworkDAO artworkDAO = ApplicationContextProvider.getCtx().getBean(
            ArtworkDAO.class);
    ProjectDAO projectDAO = ApplicationContextProvider.getCtx().getBean(
            ProjectDAO.class);
    GalleryDAO galleryDAO = ApplicationContextProvider.getCtx().getBean(
            GalleryDAO.class);
    UserDAO userDAO = ApplicationContextProvider.getCtx().getBean(UserDAO.class);

    @Override
    public Artwork createArtwork(Artwork artwork) throws ValidationException {
        User user = userService.getCurrentUser();
        if (user != null) {
            Artist artist = artistDAO.findArtistByUserId(user.getId());
            artwork.setArtistId(artist.getId());
        }
        return artworkDAO.createArtwork(artwork);
    }

    @Override
    public Artwork updateArtwork(Artwork artwork) throws ValidationException {
        return artworkDAO.updateArtwork(artwork);
    }

    @Override
    public SearchResult<ArtworkShort> searchArtworks(int startAt, int maxElements, String sortField, boolean asc) {
        User user = userService.getCurrentUser();
        if (user != null) {
            Artist artist = artistDAO.findArtistByUserId(user.getId());
            int count = artworkDAO.countArtworks(artist.getId());
            List<Artwork> results = artworkDAO.findArtworks(artist.getId(),
                    startAt, maxElements, sortField, asc);
            List<ArtworkShort> shorts = new ArrayList<ArtworkShort>(results.size());
            for (Artwork artwork : results) {
            	ArtworkShort xort = new ArtworkShort();
            	xort.setId(artwork.getId());
            	xort.setTitle(artwork.getTitle());
            	xort.setType(artwork.getType().name());
            	xort.setYear(Integer.valueOf((int)artwork.getYear()));
            	LOGGER.debug("artwork.getPhotos() [" + artwork.getPhotos() + "]");
            	if (artwork.getPhotos() != null && artwork.getPhotos().size() > 0){
            		xort.setImageId(artwork.getPhotos().get(0).getImageId());
            	}
            	xort.setFeatured(artwork.getFeatured()!=null?artwork.getFeatured():false);
            	shorts.add(xort);
            }
            return new SearchResult<ArtworkShort>(shorts, count);
        }
        return null;
    }

    private void convertTagsListToSerializable(Artwork artwork) {
        if (artwork.getTags() != null) {
            String[] tags = artwork.getTags().toArray(
                    new String[artwork.getTags().size()]);
            artwork.setTags(new ArrayList<String>());
            for (String tag : tags) {
                artwork.getTags().add(tag);
            }
        }
    }

    @Override
    public Artwork getArtwork(Long id) {
        Artwork artwork = artworkDAO.findArtworkById(id);
        convertTagsListToSerializable(artwork);
        return artwork;
    }

    @Override
    public void deletePhotoFromArtwork(Long artworkId, Long imageId) {
        Artwork artwork = artworkDAO.findArtworkById(artworkId);
        artworkDAO.deleteImageFromArtwork(artwork, imageId);
    }

    @Override
    public void deleteArtwork(Long artworkId) {
        Artwork artwork = artworkDAO.findArtworkById(artworkId);
        List<Long> projectIds = projectDAO.findProjectIdsByArtworkId(artworkId);
        for (Long projectId : projectIds) {
            Project project = projectDAO.findProjectById(projectId);
            projectDAO.deleteArtworkFromProject(project, artwork);
        }
        List<Long> galleryIds = galleryDAO.findGalleriesIdsByArtworkId(artworkId);
        for (Long galleryId : galleryIds) {
            Gallery gallery = galleryDAO.findGalleryById(galleryId);
            for (Room room : gallery.getRooms()) {
                for (RoomArtwork roomArtwork : room.getArtworks()) {
                    if (roomArtwork.getArtworkId().equals(artworkId)) {
                        galleryDAO.deleteArtworkFromRoom(room, artwork);
                    }
                }
            }
        }
        artworkDAO.deleteArtwork(artworkId);
    }

    @Override
    public List<SelectProject> getSelectProjectValues(Long artworkId) {
        List<SelectProject> result = new ArrayList<SelectProject>();
        User user = userService.getCurrentUser();
        if (user != null) {
            Artist artist = artistDAO.findArtistByUserId(user.getId());
            List<Project> projects = projectDAO.findProjects(artist.getId(), 0,
                    50);
            List<Long> artworkProjectIds = projectDAO.findProjectIdsByArtworkId(artworkId);
            for (Project project : projects) {
                SelectProject value = new SelectProject();
                value.setProjectId(project.getId());
                value.setProjectTitle(project.getTitle());
                boolean hasArtwork = false;
                for (Long artProjId : artworkProjectIds) {
                    if (artProjId.longValue() == project.getId().longValue()) {
                        hasArtwork = true;
                        break;
                    }
                }
                value.setHasArtwork(hasArtwork);
                result.add(value);
            }
        }
        return result;
    }

    @Override
    public ArtworkShort getRandomArtwork(Long userId) {
        Artist artist = artistDAO.findArtistByUserId(userId);
        Long artistId = artist.getId();
        int count = artworkDAO.countFeaturedArtworks(artistId);
        int idx = new Random(System.currentTimeMillis()).nextInt(count);
        Long id = artworkDAO.findFeaturedArtworkId(artistId, idx);
        Artwork artwork = artworkDAO.findArtworkById(id);
        ArtworkShort artShort = new ArtworkShort();
        artShort.setId(artwork.getId());
        artShort.setTitle(artwork.getTitle());
        artShort.setImageId(artwork.getPhotos().get(0).getImageId());
        return artShort;
    }

    @Override
    public void sendMessage(String email, String header, String message,
            Long artworkId) {
        Artwork artwork = artworkDAO.findArtworkById(artworkId);
        Artist artist = artistDAO.findArtistById(artwork.getArtistId());
        User user = userDAO.findUserById(artist.getUserId());
        ArtworkMessage artMsg = new ArtworkMessage();
        artMsg.setArtworkId(artworkId);
        artMsg.setArtistId(artwork.getArtistId());
        artMsg.setEmail(email);
        artMsg.setHeader(header);
        artMsg.setMessage(message);
        artMsg = artworkDAO.createMessage(artMsg);

        StringBuffer msgBody = new StringBuffer();
        msgBody.append("Hi ").append(user.getName()).append(",\n\n");
        msgBody.append("You have received a message at Judithshaylor.com.\n\n");
        msgBody.append("Please, do not reply to this message directly! You will found the sender email address below.\n\n");
        msgBody.append("A user contacted you about your artwort: [").append(
                artwork.getTitle()).append("].\n\n");
        msgBody.append("Sender email address: [").append(email).append("]\n");
        msgBody.append("Received Message: \n\n").append(message).append(
                "\n\n------------------\n\n");

        sendEmail(msgBody.toString(), header, user.getEmail());
    }

    private void sendEmail(String msgBody, String subject, String... emails) {
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        try {
            Message msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress("admin@judithshaylor.com", "Judithshaylor.com Admin"));
            for (String email : emails) {
                msg.addRecipient(Message.RecipientType.TO,
                        new InternetAddress(email));
            }
            msg.addRecipient(Message.RecipientType.BCC,
                    new InternetAddress("pedrof.costa@gmail.com"));
            msg.addRecipient(Message.RecipientType.BCC,
                    new InternetAddress("judith@judithshaylor.com"));
            msg.setSubject("[judithshaylor.com] - " + subject);
            msg.setText(msgBody);
            Transport.send(msg);

        } catch (AddressException e) {
            LOGGER.error("Error sending email!", e);
        } catch (MessagingException e) {
            LOGGER.error("Error sending email!", e);
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("Error sending email!", e);
        }
    }
}
